今天要挑戰的題目是:
題目重點
程式把使用者輸入的密碼做 Base64 編碼,然後和程式中已寫死的 encodedkey 比較;因此要拿到原密碼,只要對該 Base64 字串解碼即可。
解題流程與思路
一、獲取題目所需檔案:
wget -O SafeOpener.java "https://artifacts.picoctf.net/c/83/SafeOpener.java"
ls -l SafeOpener.java
二、查看檔案觀察原始碼:
head -n 120 SafeOpener.java
程式碼重點摘要:
encodedkey = encoder.encodeToString(key.getBytes());
...
String encodedkey = "cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz";
if (password.equals(encodedkey)) { ... }
encoder.encodeToString(key.getBytes()):
把使用者輸入 key 的 bytes 用 Base64 編成字串(Java 的 Base64 編碼)。
程式不比對原始 key,而是比對 編碼後 的字串 encodedkey(程式中給出的常數)。也就是,這個常數就是正確密碼的 Base64 編碼,所以把常數做 Base64 解碼,就能得到原始密碼。
三、用 shell 解 Base64:
在上步驟程式碼中可以看到很明顯是密碼的東西:cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz
->將其解密:echo 'cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz' | base64 -d
輸出: pl3as3_l3t_m3_1nt0_th3_saf3
將解碼結果包裝,得到正確Flag:picoCTF{pl3as3_l3t_m3_1nt0_th3_saf3}
原理簡述
Base64 是一種把二進位資料(bytes)編成 ASCII 字串的標準方法(常見於網路、檔案內嵌等)。
Java 的 Base64.getEncoder().encodeToString(bytes) 與各語言的 Base64 編解碼是互通的;因此直接把程式中那個 Base64 常數做 decode,就能得到原始 bytes 的字面內容,也就是程式一開始期待的密碼字串。
XOR、哈希等不可逆或需要額外參數的演算不同,Base64 是**可逆(可解碼)**的,這使得解題非常直接。
學習心得
題目驗證流程只是把使用者輸入的密碼轉成 Base64 字串,再跟程式裡的固定字串比對,所以只要反過來「解碼」就能拿到真正的密碼。
這題幫助我建立起良好的「程式逆向思考」習慣,當看到驗證函式時,應該先觀察它是如何比對的、是否有可逆步驟,進而找到真正的密碼。